// 1. 需要考虑函数、正则、日期、ES6新对象
// 2. 需要考虑循环引用问题
// https://www.yuque.com/jackchanel/ur8rzv/lwomzzcmgom8szg3#VEfWF
const deepClone = (target, map = new Map()) => {
  // map 存的是 target, clone映射，只有会产生自身引用的变量需要记录
  // null
  if (target === null) return null;

  // 基本数据类型或函数
  if (typeof target !== "object" || typeof target === "function") return target;

  // 后面都是引用类型，先进行循环引用检查
  if (map.has(target)) return map.get(target);

  // 特殊对象类型，但能自实现深拷贝
  if (target instanceof Date) return new Date(target);
  if (target instanceof RegExp) return new RegExp(target);
  if (target instanceof Map) {
    const clone = new Map(
      [...target].map((val, key) => [key, deepClone(val, map)])
    );
    map.set(target, clone);
    return clone;
  }
  if (target instanceof Set) {
    const clone = new Set([...target].map((val) => deepClone(val)));
    map.set(target, clone);
    return clone;
  }

  // 数组和对象无法自实现深拷贝
  const clone = Array.isArray(target) ? [] : {};
  map.set(target, clone);
  for (const key in target) {
    if (target.hasOwnProperty(key)) clone[key] = deepClone(target[key], map);
  }
  return clone;
};
